home *** CD-ROM | disk | FTP | other *** search
- /**
- *** IPDial Script program for initializing a SLIP connection
- *** Copyright (C) 1994 Jochen Wiedmann
- ***
- *** This program is free software; you can redistribute it and/or modify
- *** it under the terms of the GNU General Public License as published by
- *** the Free Software Foundation; either version 2 of the License, or
- *** (at your option) any later version.
- ***
- *** This program is distributed in the hope that it will be useful,
- *** but WITHOUT ANY WARRANTY; without even the implied warranty of
- *** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *** GNU General Public License for more details.
- ***
- *** You should have received a copy of the GNU General Public License
- *** along with this program; if not, write to the Free Software
- *** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ***
- ***
- ***
- *** This file implements the communication with the serial.device.
- ***
- ***
- *** Computer: Amiga 1200 Compiler: Dice 3.01
- ***
- *** Author: Jochen Wiedmann
- *** Am Eisteich 9
- *** 72555 Metzingen
- *** Germany
- ***
- *** Phone: (+0049) 7123 / 14881
- *** Internet: wiedmann@neckar-alb.de
- **/
-
- /**
- *** Include files
- **/
- #ifndef IPDIAL_H
- #include "IPDial.h"
- #endif
- #include <ctype.h>
- #include <devices/serial.h>
- #include <devices/timer.h>
-
- #ifndef MIN
- #define MIN(a,b) (((a)>(b))?(b):(a))
- #endif
-
- /**
- *** Local variables.
- **/
- STATIC APTR MySerReq = NULL;
- STATIC APTR MyTimeReq = NULL;
- STATIC UBYTE SerBuffer[4096];
-
- /**
- *** Cleanup function.
- **/
- VOID SerialCleanup(VOID)
- {
- DeviceIODelete(MySerReq);
- DeviceIODelete(MyTimeReq);
- }
-
- /**
- *** Table of error messages created by the serial.device.
- **/
- STATIC VOID SerialShowError(ULONG Error)
- {
- STRPTR ptr;
-
- switch(Error)
- { case 1:
- ptr = (STRPTR) "Serial device busy";
- break;
- case 2:
- ptr = (STRPTR) "Baud rate not supported";
- break;
- case 4:
- ptr = (STRPTR) "Memory error";
- break;
- case 5:
- ptr = (STRPTR) "Invalid parameters";
- break;
- case 6:
- ptr = (STRPTR) "Line error";
- break;
- case 9:
- ptr = (STRPTR) "Parity error";
- break;
- case 11:
- ptr = (STRPTR) "Timer error";
- break;
- case 12:
- ptr = (STRPTR) "Buffer overflow";
- break;
- case 13:
- ptr = (STRPTR) "No DSR";
- break;
- case 15:
- ptr = (STRPTR) "Break detected";
- break;
- default:
- ptr = (STRPTR) "Unknown error";
- break;
- }
-
- fprintf(stderr, "Serial device: %s.\n", ptr);
- }
-
- /**
- *** This function opens the serial device. It can be closed
- *** using DeviceIODelete().
- **/
- STATIC ULONG SerialDecodeProtocol(struct IOExtSer *SerReq, STRPTR Protocol)
-
- {
- if (VerboseMode)
- printf("\nSerialDecodeProtocol: Protocol %s\n", Protocol);
-
- if (stricmp((char *) Protocol, "XONXOFF") == 0)
- {
- if (VerboseMode)
- printf("SerialDecodeProtocol: Setting XON/XOFF\n");
-
- SerReq->io_SerFlags &= ~(SERF_XDISABLED|SERF_7WIRE);
- }
- else if (stricmp((char *) Protocol, "NONE") == 0)
- {
- if (VerboseMode)
- printf("SerialDecodeProtocol: Setting NONE\n");
-
- SerReq->io_SerFlags |= SERF_XDISABLED;
- SerReq->io_SerFlags &= ~SERF_7WIRE;
- }
- else if (stricmp((char *) Protocol, "RTSCTS") == 0 ||
- stricmp((char *) Protocol, "7WIRE") == 0)
- {
- if (VerboseMode)
- printf("SerialDecodeProtocol: Setting RTS/CTS and 7WIRE\n");
-
- SerReq->io_SerFlags |= (SERF_XDISABLED|SERF_7WIRE);
- }
- else
- {
- if (VerboseMode)
- printf("SerialDecodeProtocol: Unknown Protocol: %s\n", Protocol);
-
- return(FALSE);
- }
- return(TRUE);
- }
-
- ULONG SerialOpen(STRPTR DeviceName, STRPTR Protocol, ULONG Unit)
- {
- ULONG error;
- struct IOExtSer *RealSerReq;
-
- if (VerboseMode)
- printf("\nSerialOpen: Device Name %s Protocol %s\n", DeviceName, Protocol);
-
- if (!(MySerReq = DeviceIOCreate(sizeof(struct IOExtSer))))
- {
- fprintf(stderr, "Failed to open %s: Memory error.\n",
- DeviceName);
- exit(10);
- }
- RealSerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
- RealSerReq->io_SerFlags = 0;
- if (Protocol)
- {
- if (!SerialDecodeProtocol(RealSerReq, Protocol))
- {
- return(FALSE);
- }
- }
- if ((error = DeviceIOOpen(DeviceName, Unit, MySerReq, 0)))
- {
- SerialShowError(error);
- exit(10);
- }
- if (Protocol)
- {
- SerialSetProtocol(Protocol);
- }
-
- if (!(MyTimeReq = DeviceIOCreate(sizeof(struct timerequest))))
- {
- fprintf(stderr, "Failed to open timer.device: Memory error.\n");
- exit(10);
- }
- if ((error = DeviceIOOpen((STRPTR) "timer.device", UNIT_VBLANK,
- MyTimeReq, 0)))
- {
- fprintf(stderr, "Failed to open timer.device: Error %ld\n", error);
- exit(10);
- }
- return(TRUE);
- }
-
- /**
- *** This function sends a string to the serial device.
- **/
- VOID SerialSend(STRPTR str, ULONG len)
-
- {
- struct IOExtSer *req;
-
- if (VerboseMode)
- printf("\nSerialSend: %s\n", str);
-
- req = (struct IOExtSer *) DeviceIOReq(MySerReq);
- req->IOSer.io_Length = strlen((char*) str);
- req->IOSer.io_Data = str;
- DeviceIODo(MySerReq, CMD_WRITE);
- }
-
- /**
- *** This function is used to wait for a certain string.
- ***
- *** The function will return if either a timeout occurs
- *** (never happens, if timeout == -1) or if one of the
- *** strings in the args array is read from the serial.device.
- ***
- *** Result is the number of the string or -1.
- **/
- STATIC APTR waitBuffer = NULL;
- LONG SerialWait(STRPTR *args, LONG timeout)
- {
- ULONG sigs;
- ULONG rsigs;
- BYTE error;
- struct IOExtSer *SerReq;
-
- if(VerboseMode)
- {
- int i=0;
- printf("SerialWait: timeout = %d\n",timeout);
- while(args[i])
- {
- printf("SerialWait: args[%d] %s \n",i,args[i]);
- i++;
- }
- }
- SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
-
- /**
- *** Be sure, that the buffer is valid.
- **/
- if (!waitBuffer && !(waitBuffer = BufferCreate()))
- {
- perror("malloc");
- exit(10);
- }
-
- /**
- *** Clear the buffer.
- **/
- BufferClear(waitBuffer);
-
- sigs = SIGBREAKF_CTRL_C | DeviceIOSignal(MySerReq);
-
- if (timeout != -1)
- {
- struct timerequest *tr = (struct timerequest *) DeviceIOReq(MyTimeReq);
-
- tr->tr_time.tv_secs = timeout;
- tr->tr_time.tv_micro = 0;
- DeviceIOSend(MyTimeReq, TR_ADDREQUEST);
- sigs |= DeviceIOSignal(MyTimeReq);
- }
-
- for(;;)
- {
- LONG result;
-
- /**
- *** First ask, if any data is present on the serial line.
- *** May be, the string we are waiting for is already present?
- **/
- do
- {
- DeviceIODo(MySerReq, SDCMD_QUERY);
- if ((result = SerReq->IOSer.io_Actual))
- {
- SerReq->IOSer.io_Data = SerBuffer;
- SerReq->IOSer.io_Length = MIN(sizeof(SerBuffer)-1,
- SerReq->IOSer.io_Actual);
- if ((error = DeviceIODo(MySerReq, CMD_READ)))
- {
- SerialShowError(error);
- exit(10);
- }
- if (EchoMode)
- {
- int i;
-
- for (i = 0; i < SerReq->IOSer.io_Actual; i++)
- {
- putchar(SerBuffer[i]);
- }
- fflush(stdout);
- }
- BufferExtend(waitBuffer, SerBuffer, SerReq->IOSer.io_Actual);
- }
- }
- while (result);
-
-
- if ((result = BufferCheck(waitBuffer, args)) >= 0)
- {
- DeviceIOAbort(MyTimeReq);
- if(VerboseMode)
- printf("SerialWait: Exit line %d result = %d\n",__LINE__,result);
- return(result);
- }
-
- /**
- *** It isn't, send a request for one byte.
- **/
- SerReq->IOSer.io_Length = 1;
- SerReq->IOSer.io_Data = SerBuffer;
- DeviceIOSend(MySerReq, CMD_READ);
-
- rsigs = Wait(sigs);
-
- if (rsigs & SIGBREAKF_CTRL_C)
- {
- printf("Ctrl-C\n");
- exit(10);
- }
- else if (rsigs & DeviceIOSignal(MySerReq))
- {
- BYTE error;
-
- /**
- *** Data received, add it to the buffer and check for more.
- **/
- if ((error = DeviceIOWait(MySerReq)))
- {
- SerialShowError(error);
- exit(10);
- }
- if (EchoMode)
- {
- putchar(*SerBuffer);
- fflush(stdout);
- }
- BufferExtend(waitBuffer, SerBuffer, 1);
- }
- else
- { /**
- *** Timeout
- **/
- DeviceIOWait(MyTimeReq);
- DeviceIOAbort(MySerReq);
- if(VerboseMode)
- printf("SerialWait: Timeout Exit line %d\n",__LINE__);
- return(-1);
- }
- }
- if(VerboseMode)
- printf("SerialWait: Exit line %d\n",__LINE__);
- }
- /**
- *** Return buffer read by the last "Wait" command.
- **/
- STRPTR SerialWaitBuffer(VOID)
- { if (!(waitBuffer))
- {
- return((STRPTR) "");
- }
- else
- {
- return(BufferBuffer(waitBuffer));
- }
- }
- /**
- *** This function implements a terminal mode. It gives the users input
- *** to the modem and likewise the modems output to the user, as long as
- *** the user doesn't enter Ctrl-\.
- **/
- VOID SerialTerminal(STRPTR eof, ULONG echo, ULONG lineMode)
- {
- struct DosPacket *dp;
- struct MsgPort *port = NULL;
- struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
- APTR SerSendReq = NULL;
- struct IOExtSer *serSendReq;
- char buffer[128];
- char sendBuffer[256]; /* Twice the size of buffer */
- ULONG bufSize = sizeof(buffer);
- ULONG status = 10;
- BPTR cis = Input();
- ULONG sigs;
-
- if (!cis)
- {
- fprintf(stderr, "Can't use nil: as input device.\n");
- exit(10);
- }
-
- if (!echo)
- {
- lineMode = FALSE;
- }
- if (!lineMode)
- {
- if (!SetMode(cis, TRUE))
- {
- fprintf(stderr, "Can't put console into character (raw) mode.\n");
- exit(10);
- }
- bufSize = 128;
- }
-
-
- if ((dp = AllocDosObject(DOS_STDPKT, NULL)))
- { if ((port = CreateMsgPort()))
- { if ((SerSendReq = DeviceIOCreate(sizeof(struct IOExtSer))))
- {
- serSendReq = (struct IOExtSer *) DeviceIOReq(SerSendReq);
- serSendReq->IOSer.io_Device = SerReq->IOSer.io_Device;
- serSendReq->IOSer.io_Unit = SerReq->IOSer.io_Unit;
- status = 0;
- }
- }
- }
-
- if (status)
- {
- fprintf(stderr, "Memory error.\n");
- goto ExitSerialTerminal;
- }
-
- dp->dp_Type = ACTION_READ;
- dp->dp_Arg1 = ((struct FileHandle *) BADDR(cis))->fh_Arg1;
- dp->dp_Arg2 = (ULONG) buffer;
- dp->dp_Arg3 = bufSize;
- SendPkt(dp, (struct MsgPort *) ((struct FileHandle *) BADDR(cis))->fh_Type,
- port);
-
- SerReq->IOSer.io_Length = 1;
- SerReq->IOSer.io_Data = SerBuffer;
- DeviceIOSend(MySerReq, CMD_READ);
-
- sigs = (1 << port->mp_SigBit) | SIGBREAKF_CTRL_C | DeviceIOSignal(MySerReq);
-
- for(;;)
- {
- LONG rsigs;
- rsigs = Wait(sigs);
- if (rsigs & SIGBREAKF_CTRL_C)
- {
- fprintf(stderr, "Ctrl-C\n");
- status = 5;
- DeviceIOAbort(MySerReq);
- AbortPkt(port, dp);
- WaitPort(port);
- goto ExitSerialTerminal;
- }
-
- if (rsigs & (1 << port->mp_SigBit))
- { int eofSeen = FALSE;
- GetMsg(port);
- if (dp->dp_Res1 == -1)
- {
- fprintf(stderr, "Error %ld while reading input.\n", dp->dp_Res2);
- status = 10;
- }
- if (dp->dp_Res1 == 0)
- {
- eofSeen = TRUE;
- }
- else
- {
- int i, bufLen; /* Extend LF to CR/LF and send resulting string. */
- bufLen = 0;
- for (i = 0; i < dp->dp_Res1; i++)
- {
- if ((eof && *eof == buffer[i]) ||
- (!eof && !lineMode && buffer[i] == 0x1c))
- {
- eofSeen = TRUE;
- }
- if (lineMode && buffer[i] == '\n')
- {
- sendBuffer[bufLen++] = '\r';
- sendBuffer[bufLen++] = '\n';
- }
- else
- {
- sendBuffer[bufLen++] = buffer[i];
- }
- }
-
- if (bufLen > 0)
- {
- serSendReq->IOSer.io_Length = bufLen;
- serSendReq->IOSer.io_Data = sendBuffer;
- DeviceIODo(SerSendReq, CMD_WRITE);
- }
-
- if (!lineMode && echo)
- {
- fwrite(sendBuffer, bufLen, 1, stdout);
- fflush(stdout);
- }
- }
-
- if (eofSeen)
- {
- DeviceIOAbort(MySerReq);
- goto ExitSerialTerminal;
- }
- dp->dp_Type = ACTION_READ;
- dp->dp_Arg1 = ((struct FileHandle *) BADDR(cis))->fh_Arg1;
- dp->dp_Arg2 = (ULONG) buffer;
- dp->dp_Arg3 = bufSize;
- SendPkt(dp, (struct MsgPort *) ((struct FileHandle *) BADDR(cis))->fh_Type, port);
- }
-
- if (rsigs & DeviceIOSignal(MySerReq))
- {
- LONG error;
- LONG result;
-
- if ((error = DeviceIOWait(MySerReq)))
- {
- SerialShowError(error);
- AbortPkt(port, dp);
- WaitPort(port);
- goto ExitSerialTerminal;
- }
- putchar(*SerBuffer);
- fflush(stdout);
-
- do
- {
- DeviceIODo(MySerReq, SDCMD_QUERY);
- if ((result = SerReq->IOSer.io_Actual))
- {
- SerReq->IOSer.io_Data = SerBuffer;
- SerReq->IOSer.io_Length = MIN(sizeof(SerBuffer)-1,
- SerReq->IOSer.io_Actual);
- if ((error = DeviceIODo(MySerReq, CMD_READ)))
- {
- SerialShowError(error);
- exit(10);
- }
- fwrite(SerBuffer, SerReq->IOSer.io_Actual, 1, stdout);
- fflush(stdout);
- }
- }
- while (result);
-
- SerReq->IOSer.io_Length = 1;
- SerReq->IOSer.io_Data = SerBuffer;
- DeviceIOSend(MySerReq, CMD_READ);
- }
- }
-
-
- ExitSerialTerminal:
- if (dp)
- {
- FreeDosObject(DOS_STDPKT, dp);
- }
- if (port)
- {
- DeleteMsgPort(port);
- }
- if (SerSendReq)
- {
- DeviceIODelete(SerSendReq);
- }
- if (!lineMode)
- {
- SetMode(cis, FALSE);
- }
- if (status)
- {
- exit(status);
- }
- }
- /**
- *** This function shows the current serial parameters.
- **/
- VOID SerialShowParms(VOID)
- {
- STRPTR Parity, Protocol;
- struct IOExtSer *SerReq;
-
- if (VerboseMode)
- printf("\nSerialShowParms\n");
-
- SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
-
- printf("\tBaud = %ld\n", SerReq->io_Baud);
- printf("\tDataBits = %ld\n", (ULONG) SerReq->io_ReadLen);
- printf("\tStopBits = %ld\n", (ULONG) SerReq->io_StopBits);
- printf("\tBufSize = %ld\n", SerReq->io_RBufLen);
- if (SerReq->io_SerFlags & SERF_PARTY_ON)
- {
- if (SerReq->io_SerFlags & SERF_PARTY_ODD)
- {
- Parity = (STRPTR) "Odd";
- }
- else
- {
- Parity = (STRPTR) "Even";
- }
- }
- else
- {
- Parity = (STRPTR) "None";
- }
- printf("\tParity = %s\n", Parity);
- if (SerReq->io_SerFlags & SERF_7WIRE)
- {
- if (SerReq->io_SerFlags & SERF_XDISABLED)
- {
- Protocol = (STRPTR) "RTS/CTS";
- }
- else
- {
- Protocol = (STRPTR) "RTS/CTS, XON/XOFF";
- }
- }
- else
- {
- if (SerReq->io_SerFlags & SERF_XDISABLED)
- {
- Protocol = (STRPTR) "None";
- }
- else
- {
- Protocol = (STRPTR) "XON/XOFF";
- }
- }
- printf("\tProtocol = %s\n\n", Protocol);
- }
-
- /**
- *** Some functions for setting serial parameters.
- **/
- VOID SerialSetBaud(ULONG Baud)
- {
- struct IOExtSer *SerReq;
- BYTE error;
-
- if (VerboseMode)
- printf("\nSerialSetBaud: %d\n", Baud);
-
- SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
-
- SerReq->io_Baud = Baud;
- if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
- {
- SerialShowError(error);
- exit(10);
- }
- }
- VOID SerialSetDataBits(UBYTE DataBits)
-
- { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
- BYTE error;
-
- SerReq->io_ReadLen = SerReq->io_WriteLen = DataBits;
- if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
- { SerialShowError(error);
- exit(10);
- }
- }
- VOID SerialSetStopBits(UBYTE StopBits)
-
- { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
- BYTE error;
-
- SerReq->io_StopBits = StopBits;
- if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
- { SerialShowError(error);
- exit(10);
- }
- }
- VOID SerialSetBufSize(ULONG BufSize)
-
- { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
- BYTE error;
-
- if (BufSize & 0x3f)
- { fprintf(stderr,
- "Warning: BufSize must be a multiple of 64, rounding up.\n");
- BufSize = (BufSize & 0x3f) + 0x40;
- }
- SerReq->io_RBufLen = BufSize;
- if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
- { SerialShowError(error);
- exit(10);
- }
- }
- ULONG SerialSetParity(STRPTR Parity)
-
- { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
- BYTE error;
-
- if (stricmp((char *) Parity, "NONE") == 0)
- { SerReq->io_SerFlags &= ~SERF_PARTY_ON;
- }
- else if (stricmp((char *) Parity, "EVEN") == 0)
- { SerReq->io_SerFlags |= SERF_PARTY_ON;
- SerReq->io_SerFlags &= ~SERF_PARTY_ODD;
- }
- else if (stricmp((char *) Parity, "ODD") == 0)
- { SerReq->io_SerFlags |= (SERF_PARTY_ON|SERF_PARTY_ODD);
- }
- else
- { return(FALSE);
- }
-
- if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
- { SerialShowError(error);
- exit(10);
- }
- return(TRUE);
- }
- ULONG SerialSetProtocol(STRPTR Protocol)
- {
- struct IOExtSer *SerReq;
- BYTE error;
-
- if (VerboseMode)
- printf("\nSerialSetProtocol: %s\n", Protocol);
-
- SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
-
- if (!(SerialDecodeProtocol(SerReq, Protocol)))
- {
- return(FALSE);
- }
-
- if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
- {
- SerialShowError(error);
- exit(10);
- }
- return(TRUE);
- }
-